package com.wenhuitec.android.tang.util;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;

import com.github.promeg.pinyinhelper.Pinyin;


import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;


public class PrintUtil {

    private OutputStreamWriter mWriter = null;
    private OutputStream mOutputStream = null;

    private byte[] outbyte = new byte[]{0x00};
    ;
    private static int printDevice = 58;

    public static int WIDTH_PIXEL = 384;
    //public final static int WIDTH_PIXEL = 570;
    public final static int IMAGE_SIZE = 320;


    public static void setPrintDevice(int type) {
        switch (type) {
            case 58:
                printDevice = 58;
                WIDTH_PIXEL = 384;
                break;
            case 80:
                printDevice = 80;
                WIDTH_PIXEL = 570;
                break;
        }
    }

    public byte[] getOutbyte() {
        return outbyte;
    }

    /**
     * 初始化Pos实例
     *
     * @param encoding 编码
     * @throws IOException
     */
    public PrintUtil(OutputStream outputStream, String encoding) throws IOException {
        initPrinter();
    }

    public PrintUtil() throws IOException {
        initPrinter();
    }

    public byte[] print(byte[] bs) throws IOException {
        return outbyte = ArrayUtil.MergerArray(outbyte, bs);
    }

    public byte[] printRawBytes(byte[] bytes) throws IOException {
        return outbyte = ArrayUtil.MergerArray(outbyte, bytes);
    }

    /**
     * 初始化打印机
     *
     * @throws IOException
     */
    public byte[] initPrinter() throws IOException {

        byte[] temp = new byte[]{0x1B, 0x40};
        return outbyte = ArrayUtil.MergerArray(outbyte, temp);
    }

    /**
     * 打印换行
     *
     * @return length 需要打印的空行数
     * @throws IOException
     */
    public byte[] printLine(int lineNum) throws IOException {
        for (int i = 0; i < lineNum; i++) {
            byte[] temp = new byte[]{0x0A};
            outbyte = ArrayUtil.MergerArray(outbyte, temp);
        }
        return outbyte;
    }

    public byte[] printQZ() throws IOException {

        byte[] temp = new byte[]{0x1d, 0x56, 0x42, 0x00};
        return outbyte = ArrayUtil.MergerArray(outbyte, temp);

    }

    /**
     * 打印换行(只换一行)
     *
     * @throws IOException
     */
    public byte[] printLine() throws IOException {
        return printLine(1);
    }

    /**
     * 打印空白(一个Tab的位置，约4个汉字)
     *
     * @param length 需要打印空白的长度,
     * @throws IOException
     */
    public byte[] printTabSpace(int length) throws IOException {
        for (int i = 0; i < length; i++) {
            byte[] temp = new byte[]{0x09};
            outbyte = ArrayUtil.MergerArray(outbyte, temp);
        }
        return outbyte;
    }

    /**
     * 绝对打印位置
     *
     * @return
     * @throws IOException
     */
    public byte[] setLocation(int offset) throws IOException {
        byte[] bs = new byte[4];
        bs[0] = 0x1B;
        bs[1] = 0x24;
        bs[2] = (byte) (offset % 256);
        bs[3] = (byte) (offset / 256);
        return bs;
    }

    public byte[] getGbk(String stText) throws IOException {
        byte[] returnText = stText.getBytes("GBK"); // 必须放在try内才可以
        return returnText;
    }

    private int getStringPixLength(String str) {
        int pixLength = 0;
        char c;
        for (int i = 0; i < str.length(); i++) {
            c = str.charAt(i);
            if (Pinyin.isChinese(c)) {
                pixLength += 24;
            } else {
                pixLength += 12;
            }
        }
        return pixLength;
    }

    public int getOffset(String str) {
        return WIDTH_PIXEL - getStringPixLength(str);
    }

    /**
     * 打印文字
     *
     * @param text
     * @throws IOException
     */
    public byte[] printText(String text) throws IOException {
        return outbyte = ArrayUtil.MergerArray(outbyte, text.getBytes("gb2312"));
    }

    /**
     * 对齐0:左对齐，1：居中，2：右对齐
     */
    public byte[] printAlignment(int alignment) throws IOException {
        byte[] temp = new byte[]{0x1b, 0x61};
        outbyte = ArrayUtil.MergerArray(outbyte, temp);
        return outbyte = ArrayUtil.MergerArray(outbyte, (byte) alignment);
    }

    public byte[] printLargeText(String text) throws IOException {
        byte[] temp = new byte[]{0x1b, 0x21, 0x48};
        outbyte = ArrayUtil.MergerArray(outbyte, temp);
        outbyte = ArrayUtil.MergerArray(outbyte, text.getBytes("gb2312"));
        temp = new byte[]{0x1b, 0x21, 0x00};
        return outbyte = ArrayUtil.MergerArray(outbyte, temp);
    }

    public byte[] printLargeText(String text, byte size) throws IOException {
        byte[] temp = new byte[]{0x1b, 0x21, size};
        outbyte = ArrayUtil.MergerArray(outbyte, temp);
        outbyte = ArrayUtil.MergerArray(outbyte, text.getBytes("gb2312"));
        temp = new byte[]{0x1b, 0x21, 0x00};
        return outbyte = ArrayUtil.MergerArray(outbyte, temp);
    }

    public byte[] printBo(int type) throws IOException {
        if (type == 0) {
            byte[] temp = new byte[]{0x1b, 0x21, 0x48};
            outbyte = ArrayUtil.MergerArray(outbyte, temp);
            return outbyte = ArrayUtil.MergerArray(outbyte, temp);
        } else {
            byte[] temp = new byte[]{0x1b, 0x21, 0x00};
            outbyte = ArrayUtil.MergerArray(outbyte, temp);
            return outbyte = ArrayUtil.MergerArray(outbyte, temp);
        }

    }

    public byte[] printTwoColumn(String title, String content) throws IOException {
        int iNum = 0;
        byte[] byteBuffer = new byte[100];
        byte[] tmp;
        tmp = getGbk(title);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;
        tmp = setLocation(getOffset(content));
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;
        tmp = getGbk(content);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        return print(byteBuffer);
    }

    public byte[] printThreeColumn(String left, String middle, String right) throws IOException {
        int iNum = 0;
        byte[] byteBuffer = new byte[200];
        byte[] tmp = new byte[0];
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;
        tmp = getGbk(left);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;


        int pixLength = getStringPixLength(left);
        if ((pixLength > 195 && pixLength < 325)) {
//            middle = "\n\t\t   " + middle;
            tmp = getGbk(left + "\n");
            System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
            iNum += tmp.length;
        } else {
            tmp = getGbk(left);
            System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
            iNum += tmp.length;
        }

        tmp = setLocation(250);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;

        tmp = getGbk(middle);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;

        tmp = setLocation(getOffset(right + " "));
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;

        tmp = getGbk(right);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);


//
//        tmp = getGbk(left);
//        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
//        iNum += tmp.length;
//        int pixLength = getStringPixLength(left) % WIDTH_PIXEL;
//        if (pixLength > WIDTH_PIXEL / 2 || pixLength == 0) {
//            middle = "\n\t\t" + middle;
//        } else {
//            tmp = setLocation(192);
//            System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
//            iNum += tmp.length;
//        }
//        tmp = getGbk(middle);
//        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
//        iNum += tmp.length;
//        tmp = setLocation(getOffset(right));
//        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
//        iNum += tmp.length;
//        tmp = getGbk(right);
//        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        return print(byteBuffer);
    }

    public void printThreeColumn(String left1, String left, String middle, String right) throws IOException {
        int iNum = 0;
        byte[] byteBuffer = new byte[200];
        byte[] tmp = new byte[0];
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;
        tmp = getGbk(left1);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;
        int pixLength = getStringPixLength(left);
        if ((pixLength > 195 && pixLength < 325)) {
//            middle = "\n\t\t   " + middle;
            tmp = getGbk(left + "\n");
            System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
            iNum += tmp.length;
        } else {
            tmp = getGbk(left);
            System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
            iNum += tmp.length;
        }
        tmp = setLocation(250);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;
        tmp = getGbk(middle);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;
        tmp = setLocation(getOffset(right + " "));
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;
        tmp = getGbk(right);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        print(byteBuffer);
    }

    public byte[] printDashLine() throws IOException {
        if (printDevice == 58) {
            return printText("--------------------------------");
        } else {
            return printText("------------------------------------------------");
        }

//        return printText("--------------------------------");
//      return  printText("------------------------------------------------");

    }

    public byte[] printBitmap(Bitmap bmp) throws IOException {
        bmp = compressPic(bmp);
        byte[] bmpByteArray = draw2PxPoint(bmp);
        return printRawBytes(bmpByteArray);
    }

    /*************************************************************************
     * 假设一个360*360的图片，分辨率设为24, 共分15行打印 每一行,是一个 360 * 24 的点阵,y轴有24个点,存储在3个byte里面。
     * 即每个byte存储8个像素点信息。因为只有黑白两色，所以对应为1的位是黑色，对应为0的位是白色
     **************************************************************************/
    private byte[] draw2PxPoint(Bitmap bmp) {
        //先设置一个足够大的size，最后在用数组拷贝复制到一个精确大小的byte数组中
        int size = bmp.getWidth() * bmp.getHeight() / 8 + 1000;
        byte[] tmp = new byte[size];
        int k = 0;
        // 设置行距为0
        tmp[k++] = 0x1B;
        tmp[k++] = 0x33;
        tmp[k++] = 0x00;
        // 居中打印
        tmp[k++] = 0x1B;
        tmp[k++] = 0x61;
        tmp[k++] = 1;
        for (int j = 0; j < bmp.getHeight() / 24f; j++) {
            tmp[k++] = 0x1B;
            tmp[k++] = 0x2A;// 0x1B 2A 表示图片打印指令
            tmp[k++] = 33; // m=33时，选择24点密度打印
            tmp[k++] = (byte) (bmp.getWidth() % 256); // nL
            tmp[k++] = (byte) (bmp.getWidth() / 256); // nH
            for (int i = 0; i < bmp.getWidth(); i++) {
                for (int m = 0; m < 3; m++) {
                    for (int n = 0; n < 8; n++) {
                        byte b = px2Byte(i, j * 24 + m * 8 + n, bmp);
                        tmp[k] += tmp[k] + b;
                    }
                    k++;
                }
            }
            tmp[k++] = 10;// 换行
        }
        // 恢复默认行距
        tmp[k++] = 0x1B;
        tmp[k++] = 0x32;

        byte[] result = new byte[k];
        System.arraycopy(tmp, 0, result, 0, k);
        return result;
    }

    /**
     * 图片二值化，黑色是1，白色是0
     *
     * @param x   横坐标
     * @param y   纵坐标
     * @param bit 位图
     * @return
     */
    private byte px2Byte(int x, int y, Bitmap bit) {
        if (x < bit.getWidth() && y < bit.getHeight()) {
            byte b;
            int pixel = bit.getPixel(x, y);
            int red = (pixel & 0x00ff0000) >> 16; // 取高两位
            int green = (pixel & 0x0000ff00) >> 8; // 取中两位
            int blue = pixel & 0x000000ff; // 取低两位
            int gray = RGB2Gray(red, green, blue);
            if (gray < 128) {
                b = 1;
            } else {
                b = 0;
            }
            return b;
        }
        return 0;
    }

    /**
     * 图片灰度的转化
     */
    private int RGB2Gray(int r, int g, int b) {
        int gray = (int) (0.29900 * r + 0.58700 * g + 0.11400 * b); // 灰度转化公式
        return gray;
    }

    /**
     * 对图片进行压缩（去除透明度）
     *
     * @param bitmapOrg
     */
    private Bitmap compressPic(Bitmap bitmapOrg) {
        // 获取这个图片的宽和高
        int width = bitmapOrg.getWidth();
        int height = bitmapOrg.getHeight();
        // 定义预转换成的图片的宽度和高度
        int newWidth = IMAGE_SIZE;
        int newHeight = IMAGE_SIZE;
        Bitmap targetBmp = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
        Canvas targetCanvas = new Canvas(targetBmp);
        targetCanvas.drawColor(0xffffffff);
        targetCanvas.drawBitmap(bitmapOrg, new Rect(0, 0, width, height), new Rect(0, 0, newWidth, newHeight), null);
        return targetBmp;
    }


//
//    public static void printTest(PrintVO printVO) {
//        byte[] temp=new byte[]{0x00};
//        outbyte=temp;
//        try {
//            PrintUtil pUtil = new PrintUtil();
//
//            // 店铺名 居中 放大
//            pUtil.printAlignment(1);
//            pUtil.printLargeText(SysConst.getInfoBate().getDriverName());
//            pUtil.printLine();
//            pUtil.printAlignment(0);
//            pUtil.printLine();
//
//            pUtil.printTwoColumn("时间:", printVO.getTime());
//            pUtil.printLine();
//            pUtil.printTwoColumn("订单号:", printVO.getShoppingCart().getOrder());
//            pUtil.printLine();
//            if (printVO.getType()==2){
//                pUtil.printTwoColumn("IC卡姓名:", printVO.getCardname());
//            }
//            pUtil.printTwoColumn("收款人:", printVO.getName());
//            pUtil.printLine();
//            // 分隔线
//            pUtil.printDashLine();
//            pUtil.printLine();
//            //打印商品列表
//            pUtil.printText("商品");
//            pUtil.printTabSpace(2);
//            pUtil.printText("数量");
//            pUtil.printTabSpace(3);
//            pUtil.printText("    小计");
//            pUtil.printLine();
//            for (Shopping goo : printVO.getShoppingCart().getShoppings()) {
//                pUtil.printThreeColumn(goo.getName(), String.valueOf(goo.getAmout()), String.valueOf(goo.getJe()));
//            }
//            pUtil.printDashLine();
//            pUtil.printLine();
//
//            pUtil.printTwoColumn("合计数量:", String.valueOf(printVO.getShoppingCart().getSectionnum()));
//            pUtil.printLine();
//
//            pUtil.printTwoColumn("合计金额:", String.valueOf(printVO.getShoppingCart().getTotal()));
//            pUtil.printLine();
//            if (printVO.getType()==2) {
//                if (printVO.getBt() == 0) {
//                    pUtil.printTwoColumn("支付方式：:", "IC卡支付(自购)");
//                    pUtil.printTwoColumn("上次自购余额：:", String.valueOf(printVO.getLastje()));
//                    pUtil.printTwoColumn("本次自购余额：:", String.valueOf(printVO.getJe()));
//                    pUtil.printTwoColumn("本次补贴余额：:", String.valueOf(printVO.getJe2()));
//                } else {
//                    pUtil.printTwoColumn("支付方式：:", "IC卡支付(补贴)");
//                    pUtil.printTwoColumn("上次补贴余额：:", String.valueOf(printVO.getLastje()));
//                    pUtil.printTwoColumn("本次补贴余额：:", String.valueOf(printVO.getJe2()));
//                    pUtil.printTwoColumn("本次自购余额：:", String.valueOf(printVO.getJe()));
//                }
//            }
//            if(printVO.getType()==1){
//                pUtil.printTwoColumn("支付方式：:", "IC卡支付");
//            }
//            if(printVO.getType()==3){
//                pUtil.printTwoColumn("支付方式：:", "扫码支付");
//            }
//            pUtil.printDashLine();
//            // pUtil.printBitmap(bitmap);
//            pUtil.printLine(3);
//            pUtil.printQZ();
////            0x1d 0x56 0x42 0x00
//            AidlUtil.getInstance().sendRawData(outbyte);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }


}